package com.suixun.util.encode;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Random;

/**
 * AspireAes.java
 *
 * @author <a href="mailto:huangy@17find.com">hellmash</a>
 * @version create on 2015-08-20 17:24
 *          <p>
 *          CopyRight(c)2015 杭州随寻科技有限公司 17find.com 版权所有
 */
public class AspireAes {

    private static AspireAes instance = null;

    private Cipher cipher;

    SecretKeySpec key = null;

    AlgorithmParameterSpec iv = null;

    public static AspireAes getInstance() {
        String key = "0123456789abcdef0123456789abcdef", iv = "0123456789abcdef0123456789abcdef";
        return getInstance(key, iv);
    }

    public static AspireAes getInstance(String key, String iv) {

        instance = new AspireAes(key, iv);

        return instance;
    }

    /**
     * 将32bytes的16禁止串压缩成16bytes，充分利用128bits的密钥空间
     *
     * @param hex
     * @return byte[]
     */
    public static byte[] packHex(String hex) {
        int len = hex.length() >> 1;
        byte[] b = new byte[len];
        short k = 0;
        for (int i = 0, j = 0; i < len; i++, j = i << 1) {
            k = Short.parseShort(hex.substring(j, j + 2), 16);
            b[i] = (byte) (k & 0xff);
        }
        return b;
    }

    public static String sha1(String s) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        byte[] b = MessageDigest.getInstance("sha1").digest(s.getBytes("UTF-8"));
        return byte2hex(b);
    }

    public static String byte2hex(byte[] b) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            if (b[i] >= 0 && b[i] < 16) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(b[i] & 0xff));
        }
        return sb.toString();
    }

    /**
     * 生成可打印的指定长度的随机字符串 asc码范围[32,126]
     *
     * @param length
     * @return
     */
    public static String getRandStr(int length) {
        Random r = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            sb.append((char) (r.nextInt(127 - 32) + 32));
        }
        return sb.toString();
    }

    private AspireAes(String keyStr, String ivStr) {
        try {
            iv = new IvParameterSpec(packHex(ivStr));
            key = new SecretKeySpec(packHex(keyStr), "AES");
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    private void initParam(String keyStr, String ivStr) {
        try {
            iv = new IvParameterSpec(packHex(ivStr));
            key = new SecretKeySpec(packHex(keyStr), "AES");
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 加密
     *
     * @param     txt
     *
     * @return String
     */
    public byte[] encrypt(byte[] txt) {
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key, iv);
            return cipher.doFinal(txt);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 加密
     *
     * @param  txt
     *
     * @return String
     */
    public String encrypt(String txt) {
        try {
            byte[] b = this.encrypt(txt.getBytes("utf-8"));
            return Base64.encodeBase64URLSafeString(b);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 加密
     *
     * @param String
     *            txt
     *
     * @return String
     */
//    public String encrypt(String txt, int flags) {
//        try {
//            byte[] b = this.encrypt(txt.getBytes("utf-8"));
//            return Base64.encodeToString(b, 0, b.length, flags);
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    /**
     * 解密
     *
     * @param  txt
     *
     * @return String
     */
    public byte[] decrypt(byte[] txt) {
        try {
            cipher.init(Cipher.DECRYPT_MODE, key, iv);
            return cipher.doFinal(txt);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 加密
     *
     * @param  txt
     *
     * @return String
     */
    public String decrypt(String txt) {

        try {
            cipher.init(Cipher.DECRYPT_MODE, key, iv);
            byte[] b = txt.getBytes();
            b = Base64.decodeBase64(b);
            b = cipher.doFinal(b);
            return new String(b, "utf-8");
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void test() {
        String txt = "{\"appkey\" : \"4ed1ffaad9a78a1a\",\"appsecret\" : \"fe0144ca9ab1219dad3c94ad0e1f491d\",\"phone\" : \"18656419675\"}";
        AspireAes aes = AspireAes.getInstance("0123456789abcdef0123456789abcdef","0123456789abcdef0123456789abcdef");
        //AspireAes aes = AspireAes.getInstance();
        String x = aes.encrypt(txt);
        System.out.print("加密：" + txt + "\r\n" + x + "\r\n");
        txt = x;
        x = aes.decrypt("5ciCB-M9mnFvrDjPQvj4FN6xZ9eSqrRCCtqPmpSAY-tWgwmMUt8ES_gQHe4m3qQZFde3b28JDNhNTxUBjHUxEmL-RUfYjGJiOaNK-90jdHGwX47Jq3k5dooOgUwWiWBb1bZwMqLiNVIsM5Jvd5YfRw");
        System.out.print("解密：" + x + "\r\n");

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(getRandStr(16));
        test();
    }

}
